using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using Microsoft.Data.Schema.Extensibility;
using Microsoft.Data.Schema.SchemaModel;
using Microsoft.Data.Schema.ScriptDom.Sql;
using Microsoft.Data.Schema.Sql.SchemaModel;
using Microsoft.Data.Schema.Sql;
using Microsoft.Data.Schema.StaticCodeAnalysis;
using System.Text.RegularExpressions;

namespace CallCreditStandards
{
    /// <summary>
    /// This is a SQL rule which returns a warning message 
    /// whenever there is a ........................................
    /// This rule only applies to .................................
    /// </summary>

    [DatabaseSchemaProviderCompatibility(typeof(SqlDatabaseSchemaProvider))]
    [DataRuleAttribute(
        CallCreditStandardsConstants.NameSpace,
        CallCreditStandardsConstants.CheckNonProjectObjectsAreCreatedLocallyInUsingCodeRuleId,
        CallCreditStandardsConstants.ResourceBaseName,
        CallCreditStandardsConstants.CheckNonProjectObjectsAreCreatedLocallyInUsingCode_RuleName,
        CallCreditStandardsConstants.CategoryDatabaseStructures,
        DescriptionResourceId = CallCreditStandardsConstants.CheckNonProjectObjectsAreCreatedLocallyInUsingCode_ProblemDescription)]
    [SupportedElementType(typeof(ISqlProcedure))]
    [SupportedElementType(typeof(ISqlTrigger))]
    [SupportedElementType(typeof(ISqlFunction))]
    [SupportedElementType(typeof(ISqlView))]
    [SupportedElementType(typeof(ISqlTable))]
    public class CheckNonProjectObjectsAreCreatedLocallyInUsingCodeRule : StaticCodeAnalysisRule
    {
        #region Overrides
        /// <summary>
        /// Analyze the model element
        /// </summary>
        public override IList<DataRuleProblem> Analyze(DataRuleSetting ruleSetting, DataRuleExecutionContext context)
        {
            // (Re)-Load Environment settings
            CallCreditSettings.LoadSettings();
            // Get Model collation 
            SqlComparer.Comparer = context.SchemaModel.Comparer;
        
            List<DataRuleProblem> problems = new List<DataRuleProblem>();

            IModelElement modelElement = context.ModelElement;

            // casting to SQL specific 
            SqlSchemaModel sqlSchemaModel = modelElement.Model as SqlSchemaModel;
            Debug.Assert(sqlSchemaModel != null, "SqlSchemaModel is expected");

            ISqlModelElement sqlElement = modelElement as ISqlModelElement;
            Debug.Assert(sqlElement != null, "ISqlModelElement is expected");

            // Get ScriptDom for this model element
            TSqlFragment sqlFragment = context.ScriptFragment as TSqlFragment;
            Debug.Assert(sqlFragment != null, "TSqlFragment is expected");

            // visitor to get the occurrences of statements 
            CheckNonProjectObjectsAreCreatedLocallyInUsingCodeVisitor templateVisitor = new TemplateVisitor();
            sqlFragment.Accept(templateVisitor);
            List<TSqlFragment> issues = templateVisitor.Objects;


            // Create problems for each object
            foreach (TSqlFragment issue in issues)
            {
                DataRuleProblem problem = new DataRuleProblem(this,
                                            String.Format(CultureInfo.CurrentCulture, this.RuleProperties.Description, SqlRuleUtils.GetElementName(sqlSchemaModel, sqlElement)),
                                            sqlElement);

                SqlRuleUtils.UpdateProblemPosition(problem, issue.StartOffset, issue.FragmentLength);
                problems.Add(problem);
            }


            return problems;
        }

        #endregion    
 
    }
}
